
#include "lcd.h"
#include "prospeckz.h"
#include "font.h"

unsigned char currX = 0;
unsigned char currY = 0;

void lcd_maybe_get_pos(unsigned char *x, unsigned char *y)
{

	*x = currX;
	*y = currY;

}

void lcd_do_setup(void)
{

	ClearPin(CS);
	ClearPin(RES);
	ClearPin(RS);
	ClearPin(WR);
	ClearPin(RD);
	
	lcd_setup();

	lcd_clear();
}

void lcd_print_rle_bitmap_pos(const char* s, unsigned char x, unsigned char y)
{
	char count, symbol;
	unsigned char a,b, maxX, maxY;
	lcd_set_pos(y,x);
	a = y;
	b = x;
	maxX = *s++ + b;
	maxY = *s++;
	maxY /= 8;
	maxY += a;
	
	while(*s)
	{
		int i;
		count = *s;
		s++;
		symbol = *s;
		s++;
		
		for(i=0;i<count;i++)
		{
			lcd_write(symbol);
		}
		b += count;

		//if we've reached the end of this page, go on to the next page.
		if(b >= maxX)
		{
			b = x;
			a++;
			lcd_set_pos(a,x);
		}
	}
}

void lcd_print_rle_bitmap(const char *s)
{
	char count, symbol;
	unsigned char a,b;
	a = 0;
	b = 0;
	lcd_set_pos(0,0);
	
	while(*s)
	{
		int i;
		count = *s;
		s++;
		symbol = *s;
		s++;
		
		for(i=0;i<count;i++)
		{
			lcd_write(symbol);
		}
		b += count;

		//if we've reached the end of this page, go on to the next page.
		if(b >= 128)
		{
			b = 0;
			a++;
			lcd_set_pos(a,0);
		}
	}
}



//################################################
/** \file lcd.c
  * \author Andy Koppe
  * \brief KS0713 LCD driver
  */






void lcd_fill_rect(unsigned char p,unsigned char c,unsigned char h, unsigned char w, unsigned char pat)
{
  unsigned char i;
  do {
    lcd_set_pos(p++,c);
	i = w;
	do lcd_write(pat); while (--i);
  } while (--h);
}

void lcd_clear_rect(unsigned char p,unsigned char c,unsigned char h, unsigned char w) 
{
  lcd_fill_rect(p,c,h,w,0);
}

void lcd_clear(void)
{
  lcd_fill_rect(0,0,8,128,0);
}




void lcd_print_full_bitmap(const char *s)
{
	int a, b;
	for(a = 0; a < 8; a++){
		lcd_set_pos(a,0);
		for (b = 0; b < 128; b++){
	    	lcd_write(*s);
			s++;
		}
	}
  //while (*s  != 0){

}


static void pause(unsigned char loops){
	int x,y;
	for (x=0; x<loops; x++)
		for (y=0; y<256; y++);

}
void SetPins(unsigned char c){
	if(c >= 128) {SetPin(P07); c -= 128;
    }else{ ClearPin(P07);}
	
	if(c >= 64) {SetPin(P06); c -= 64;
    }else{ ClearPin(P06);}
	
	if(c >= 32) {SetPin(P05); c -= 32;
    }else{ ClearPin(P05);}
	
	if(c >= 16) {SetPin(P04); c -= 16;
    }else{ ClearPin(P04);}
	
	if(c >= 8) {SetPin(P03); c -= 8;
    }else{ ClearPin(P03);}
	
	if(c >= 4) {SetPin(P02); c -= 4;
    }else{ ClearPin(P02);}
	
	if(c >= 2) {SetPin(P01); c -= 2;
    }else{ ClearPin(P01);}

	if(c >= 1) {SetPin(P00); c -= 1;
    }else{ ClearPin(P00);}

}




// initialise LCD interface
static void lcd_init(void) 
{
  // enable, Intel parallel mode, data selected, reset & write & read inactive
  //LCD_CO |= 1<<LCD_WR | 1<<LCD_RD | 1<<LCD_CS;
  SetPin(WR); SetPin(RD); SetPin(CS);
  
  //LCD_CD |= 1<<LCD_CS | 1<<LCD_RES | 1<<LCD_WR | 1<<LCD_RD | 1<<LCD_RS;
  SetPin(CS); SetPin(RES); SetPin(WR); SetPin(RD); SetPin(RS);
  //LCD_DO = 0x00;
  SetPins(0);
  //LCD_DD = 0x00;
}

// reset LCD
static void lcd_reset(void)
{
  //LCD_CO &= ~(1<<LCD_RES);
  ClearPin(RES);
  pause(100);
  //Radio_delay(100);
  //LCD_CO |= 1<<LCD_RES;
  SetPin(RES);
  pause(100);
  //Radio_delay(100);
}

// write data to LCD
void lcd_write(unsigned char b) 
{
  //LCD_CO |= 1<<LCD_RS;
  SetPin(RS);
  //LCD_DO = b;
  //LCD_DD = 0xff;
  SetPins(b);
  //LCD_CO &= ~(1<<LCD_WR);
  ClearPin(WR);
  //LCD_CO |= 1<<LCD_WR;
  SetPin(WR);
  //LCD_DD = 0;
  //LCD_DO = 0;
  SetPins(0);
}

/* NO READING JUST NOW
// read data from LCD
uint8 
lcd_read(void) 
{
  LCD_CO |= 1<<LCD_RS;
  LCD_CO &= ~(1<<LCD_RD);
  uint8 b = LCD_DI;
  LCD_CO |= 1<<LCD_RD;
  return b;
}

void
lcd_xor(uint8 b) 
{
  //lcd_read();
  //lcd_write(lcd_read() ^ b);
  LCD_CO |= 1<<LCD_RS;
  LCD_CO &= ~(1<<LCD_RD);
  LCD_CO |= 1<<LCD_RD;
  LCD_CO &= ~(1<<LCD_RD);
  LCD_CO |= 1<<LCD_RD;
  LCD_CO &= ~(1<<LCD_RD);
  uint8 a = LCD_DI;
  LCD_CO |= 1<<LCD_RD;
  LCD_DO = a ^ b;
  LCD_DD = 0xff;
  LCD_CO &= ~(1<<LCD_WR);
  LCD_CO |= 1<<LCD_WR;
  LCD_DD = 0;
  LCD_DO = 0;
} 

void
lcd_mask(uint8 on, uint8 off) 
{
  //lcd_read();
  //lcd_write(lcd_read() ^ b);
  LCD_CO |= 1<<LCD_RS;
  LCD_CO &= ~(1<<LCD_RD);
  LCD_CO |= 1<<LCD_RD;
  LCD_CO &= ~(1<<LCD_RD);
  LCD_CO |= 1<<LCD_RD;
  LCD_CO &= ~(1<<LCD_RD);
  uint8 b = LCD_DI;
  LCD_CO |= 1<<LCD_RD;
  LCD_DO = (b & off) ^ on;
  LCD_DD = 0xff;
  LCD_CO &= ~(1<<LCD_WR);
  LCD_CO |= 1<<LCD_WR;
  LCD_DD = 0;
  LCD_DO = 0;
}
 */


// write a command to LCD
static void lcd_command(unsigned char b) 
{
  //LCD_CO &= ~(1<<LCD_RS);
  ClearPin(RS);
  //LCD_DO = b;
  //LCD_DD = 0xff;
  SetPins(b);
  //LCD_CO &= ~(1<<LCD_WR);
  ClearPin(WR);
  //LCD_CO |= 1<<LCD_WR;
  SetPin(WR);
  //LCD_DD = 0;
  //LCD_DO = 0;
  SetPins(0);
}
/* NO RAEDING FOR NOW
// read status from LCD
static uint8 
lcd_status(void) 
{
  LCD_CO &= ~(1<<LCD_RS);
  LCD_CO &= ~(1<<LCD_RD);
  uint8 b = LCD_DI;
  LCD_CO |= 1<<LCD_RD;
  return b;
}*/

static  void lcd_soft_reset(void) { lcd_command(0xE2); }

static  void lcd_display(unsigned char b) { lcd_command(0xAE|b); }


static  void lcd_set_voltage(unsigned char b) { lcd_command(0x81); lcd_command(b); }

static  void lcd_set_resistor(unsigned char b) { lcd_command(0x20|b); }

static  void lcd_power_control(unsigned char b) { lcd_command(0x28|b); }


static  void lcd_set_shl(unsigned char b) { lcd_command(0xC0 | b << 3); }

static  void lcd_set_adc(unsigned char b) { lcd_command(0xA0|b); }

static  void lcd_set_bias(unsigned char b) { lcd_command(0xA2|b); }

static  void lcd_set_black(unsigned char b) { lcd_command(0xA4|b); }

static  void lcd_set_reverse(unsigned char b) { lcd_command(0xA6|b); }


static  void lcd_set_modify_read(void) { lcd_command(0xE0); }

static  void lcd_reset_modify_read(void) { lcd_command(0xEE); }


static  void lcd_set_initial_line(unsigned char b) { lcd_command(0x40&b); }

void lcd_set_page(unsigned char p) { lcd_command(0xB0|p); }

void lcd_set_col(unsigned char c) { lcd_command(0x10|(c>>4)); lcd_command(c&0xF); }

void lcd_set_pos(unsigned char p, unsigned char c)
{ 

  lcd_command(0xB0|p);
  lcd_command(0x10|(c>>4)); 
  lcd_command(c&0xF);
  currY = p;
  currX = c;
  
}


void lcd_setup(void)
{
  lcd_init();
  lcd_reset();
  lcd_power_control(4);
  pause(1000);
  lcd_power_control(6);
  pause(1000);
  lcd_power_control(7);
  pause(1000);
  lcd_set_resistor(5);
  lcd_set_voltage(36);
  lcd_display(1);
  pause(1000);

  lcd_set_shl(1);
  lcd_set_modify_read();
}

//#############################################

void lcd_print_char(char c)
{

  //if (c >= ' ' && c <= 'Z') {
    //const unsigned char *glyph = glyphs[c - ' '];
	int place;
	int a;
	place = c * 8;

	for (a = 0; a < 8; a++){
	  lcd_write(fontdata[place++]);}
    lcd_write(0);
	currX++;
  //}
  
}

void lcd_print_cstring(const char* s)
{
	while (*s  != 0){
    lcd_print_char(*s);
	s++;
	}
}

void lcd_print_string(char *s)
{

  while (*s  != 0){
    lcd_print_char(*s);
	s++;
	}

}

/*
void
lcd_print_string(const char *s)
{
  while (*s  != 0){
    lcd_print_char(*s);
	s++;
	}
}
*/
